from by.vaukalak.core.net.socket.SocketServer import *;
from by.vaukalak.core.net.socket.SocketEvent import *;
from by.vaukalak.core.net.commands.CommandSerializer import *;
from by.vaukalak.core.events.EventDispatcher import EventDispatcher;
from game.PlayerEvent import PlayerEvent;
from core import PlayerColor;
from core import PeaceType;
from core.PeacePosition import PeacePosition;

class Player(EventDispatcher):
    def __init__(self, conn, db, name, userId, color):
        EventDispatcher.__init__(self);
        self._name = name;
        self._db = db;
        self._userId = db.createNewPlayerIfNotExist(userId, name);
        self.connection = conn;
        self.connection.addEventListener(SocketEvent.DATA_RECIVED, self._onDataRecived);
        self.connection.addEventListener(SocketEvent.CONNECTION_INTERRUPED, self._onConnectionInterruped);
        self.color = color;
        self._serializer = CommandSerializer();
        self.rulesController = None;
        self.alreadyOnTron = False;
        self._isConnected = True;

    @property
    def isConnected(self):
        return self._isConnected;

    def _onConnectionInterruped(self, event):
        print "connection interruped";
        self._isConnected = False;
        self.dispatchEvent(PlayerEvent(PlayerEvent.DISCONNECTED, None));

    def _onDataRecived(self, event):
        command = self._serializer.deserialize(event.data);
        #print event.data;
        if command.name == "motionRequest":
            self.dispatchEvent(PlayerEvent(PlayerEvent.MOTION_REQUEST, command));
        if command.name == "selectPeace":
            self.dispatchEvent(PlayerEvent(PlayerEvent.SELECT_PEACE, command));

    @property
    def name(self):
        return self._name;

    @property
    def userId(self):
        return self._userId;

    @property
    def canPutOnRokash(self):
        self.rulesController.switchPlayer();
        ownPeaces = self.rulesController.boardData.getPeaceByColor(self.color);
        for peacePos in ownPeaces:
            #print peacePos.serialize();
            countY = 0;
            for row in self.rulesController.boardData.matrix:
                countX = 0;
                for cell in row:
                    if(self.rulesController.testMotion(peacePos, PeacePosition(countX, countY))):
                        self.rulesController.boardData.rollBackAll();
                        self.rulesController.switchPlayer();
                        return True;
                    self.rulesController.boardData.rollBackAll();
                    countX = countX + 1;
                countY = countY + 1;
        self.rulesController.switchPlayer();
        return False;

    @property
    def canRunFromCheck(self):
        self.rulesController.switchPlayer();
        ownPeaces = self.rulesController.boardData.getPeaceByColor(self.color);
        for peacePos in ownPeaces:
            countY = 0;
            for row in self.rulesController.boardData.matrix:
                countX = 0;
                for cell in row:
                    if(self.rulesController.testMotion(peacePos, PeacePosition(countX, countY))):
                        self.rulesController.boardData.rollBackAll();
                        self.rulesController.switchPlayer();
                        return True;
                    self.rulesController.boardData.rollBackAll();
                    countX = countX + 1;
                countY = countY + 1;
        self.rulesController.switchPlayer();
        return False;

    @property
    def isUnderRokash(self):
        if(not self.hasNobelOnTron):
            return False;
        if(self.color == PlayerColor.WHITE):
            enemyPeaces = self.rulesController.boardData.getPeaceByColor(PlayerColor.BLACK);
        else:
            enemyPeaces = self.rulesController.boardData.getPeaceByColor(PlayerColor.WHITE);
        tronCell = PeacePosition(4,4);
        for item in enemyPeaces:
            cellValue = self.rulesController.boardData.getPeaceByCell(item);
            if(self.rulesController.getPeaceLogic(cellValue).checkMotion(item, tronCell)):
                return True;
        return False;

    @property
    def hasNobelOnTron(self):
        return self.rulesController.boardData.getPeaceByCell(PeacePosition(4,4)) in self._ownPeaces;


    @property
    def isUnderCheck(self):
        if(self.hasKniazhych):
            return False;
        if(self.color == PlayerColor.WHITE):
            enemyPeaces = self.rulesController.boardData.getPeaceByColor(PlayerColor.BLACK);
        else:
            enemyPeaces = self.rulesController.boardData.getPeaceByColor(PlayerColor.WHITE)
        kniazCell = self.rulesController.boardData.getPeaceByType(self._kniazType)[0];
        for item in enemyPeaces:
            cellValue = self.rulesController.boardData.getPeaceByCell(item);
            if(self.rulesController.getPeaceLogic(cellValue).checkMotion(item, kniazCell)):
                return True;
        return False;

    @property
    def hasKniazhych(self):
        return len(self.rulesController.boardData.getPeaceByType(self._kniazhychType)) > 0;

    @property
    def hasKniaz(self):
        return len(self.rulesController.boardData.getPeaceByType(self._kniazType)) > 0;

    def declareKniaz(self):
        cell = self.rulesController.boardData.getPeaceByType(self._kniazhychType)[0];
        self.rulesController.boardData.matrix[cell.y][cell.x] = self._kniazType;
        return cell, self._kniazType;

    @property
    def _kniazType(self):
        if(self.color == PlayerColor.WHITE):
            return PeaceType.WHITE_KNIAZ;
        else:
            return PeaceType.BLACK_KNIAZ;

    @property
    def _kniazhychType(self):
        if(self.color == PlayerColor.WHITE):
            return PeaceType.WHITE_KNIAZHYCH;
        else:
            return PeaceType.BLACK_KNIAZHYCH;

    @property
    def _ownPeaces(self):
        if(self.color == PlayerColor.WHITE):
            return PeaceType.WHITE_PEACES;
        else:
            return PeaceType.BLACK_PEACES;

    @property
    def _opponent(self):
        if(self == self.rulesController.currentPlayer):
            return self.rulesController.opponentPlayer;
        else:
            return self.rulesController.currentPlayer;

    @property
    def hasToPromovePawn(self):
        countX = 0;
        if(self.color == PlayerColor.WHITE):
            for cell in self.rulesController.boardData.matrix[0]:
                if cell == PeaceType.WHITE_PAWN:
                    return PeacePosition(countX, 0);
                countX = countX + 1;
        else:
            for cell in self.rulesController.boardData.matrix[8]:
                if cell == PeaceType.BLACK_PAWN:
                    return PeacePosition(countX, 8);
                countX = countX + 1;
        return None;

    @property
    def vaukalakType(self):
        if self.color == PlayerColor.WHITE:
            return PeaceType.WHITE_VAUKALAK;
        else:
            return PeaceType.BLACK_VAUKALAK;

    @property
    def missingPeaces(self):
        peaces = list();
        if(self.color == PlayerColor.WHITE):
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.WHITE_LADZIA)) < 2:
                peaces.append(PeaceType.WHITE_LADZIA);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.WHITE_GARMATA)) < 2:
                peaces.append(PeaceType.WHITE_GARMATA);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.WHITE_VAUKALAK)) < 2:
                peaces.append(PeaceType.WHITE_VAUKALAK);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.WHITE_GETMAN)) < 1:
                peaces.append(PeaceType.WHITE_GETMAN);
        else:
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.BLACK_LADZIA)) < 2:
                peaces.append(PeaceType.BLACK_LADZIA);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.BLACK_GARMATA)) < 2:
                peaces.append(PeaceType.BLACK_GARMATA);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.BLACK_VAUKALAK)) < 2:
                peaces.append(PeaceType.BLACK_VAUKALAK);
            if len(self.rulesController.boardData.getPeaceByType(PeaceType.BLACK_GETMAN)) < 1:
                peaces.append(PeaceType.BLACK_GETMAN);
        return peaces;

    def send(self, command):
        response = self._serializer.serialize(command);
        #print response;
        self.connection.send(response);